﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace GameNodeProgramm
{
    class GameLogic
    {
        Random rnd;
        Drawer dr = new Drawer('$');
        GameField field = new GameField(5, 8, 5, 5); //размер поля

        public ConsoleNode targetNode;
        public CustomerNode smartNode;
        public List<ConsoleNode> nextRound;
        public List<ConsoleNode> nodes;
        public int charNumber;
        public byte consoleColorCounter;

        public GameLogic()
        {
            rnd = new Random();
            nextRound = new List<ConsoleNode>();
            nodes = new List<ConsoleNode>();
            charNumber = 65;
            consoleColorCounter = 2;
        }
        public void FillListOfNodes(int amountOfNodes)
        {
            nodes.Add(new ConsoleNode(rnd.Next(field.StartX, field.StartX + field.Width - 1), rnd.Next(field.StartY, field.StartY + field.Height - 1),
                (char)charNumber, (ConsoleColor)consoleColorCounter));
            for (int i = 1; i < amountOfNodes; i++)
            {
                nodes.Add(GenerateUniqueNode());
            }
        }

        public ConsoleNode GenerateUniqueNode()
        {
            bool done = false;
            int newNodeX;
            int newNodeY;
            do
            {
                newNodeX = rnd.Next(field.StartX, field.StartX + field.Width - 1);
                newNodeY = rnd.Next(field.StartY, field.StartY + field.Height - 1);
                if (isUniqueCoordinates(newNodeX, newNodeY))
                {
                    if (consoleColorCounter == 15)
                    { consoleColorCounter = 2; }
                    charNumber++;
                    consoleColorCounter++;
                    done = true;
                }
            }
            while (done == false);
            return new ConsoleNode(newNodeX, newNodeY, (char)charNumber, (ConsoleColor)consoleColorCounter);
        }

        //public ConsoleNode UpdateCoordinates()
        //{
        //    return 
        //}

        public bool isUniqueCoordinates(int coordX, int coordY)
        {
            foreach (var node in nodes)
            {
                if (coordY != node.Y && coordX != node.X)
                    return true;
            }
            return false;
        }

        public ConsoleNode GenerateTargetNode()
        {
            bool done = false;
            int newNodeX;
            int newNodeY;
            do
            {
                newNodeX = rnd.Next(field.StartX, field.StartX + field.Width - 1);
                newNodeY = rnd.Next(field.StartY, field.StartY + field.Height - 1);
                if (isUniqueCoordinates(newNodeX, newNodeY))
                {
                    done = true;
                }
            }
            while (done == false);
            return new ConsoleNode(newNodeX, newNodeY, (char)21, (ConsoleColor)12);
        }

        public CustomerNode GenerateSmartNode()
        {
            bool done = false;
            int newNodeX;
            int newNodeY;
            do
            {
                newNodeX = rnd.Next(field.StartX, field.StartX + field.Width - 1);
                newNodeY = rnd.Next(field.StartY, field.StartY + field.Height - 1);
                if (isUniqueCoordinates(newNodeX, newNodeY))
                {
                    done = true;
                }
            }
            while (done == false);
            return new CustomerNode(newNodeX, newNodeY, '~', ConsoleColor.DarkYellow);
        }

        public void StartGame()
        {
            FillListOfNodes(1);
            targetNode = GenerateTargetNode();
            nodes.Add(GenerateSmartNode());
            bool isGameOver = false;
            do
            {
                Console.Clear();
                bool isNewRound = false;
                do
                {
                    dr.DraweGameFieldFrame(field);
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        nodes[i].Move(CheckPosition);
                        if (targetNode.Y == nodes[i].Y && targetNode.X == nodes[i].X)
                        {
                            nextRound.Add(nodes[i]);
                            nodes.RemoveAt(i);
                            if (nodes.Count == 1)
                            {
                                WriteLooserList(nodes);
                                WriteWinnersList(nextRound);
                                //isNewRound = true;
                            }
                        }
                        foreach (var gameNode in nodes)
                        {
                            dr.DrawGameNode(gameNode);
                            dr.DrawGameNode(targetNode);
                        }
                        Thread.Sleep(100);
                        foreach (var item in nodes)
                        {
                            dr.ClearGameNode(item);
                        }
                    }
                }
                while (!isNewRound);
                Console.ReadKey();

                if (nextRound.Count == 1)
                {
                    isGameOver = true;
                }
                else
                {
                    nodes = nextRound;
                    nextRound = new List<ConsoleNode>();
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        nodes[i] = GenerateUniqueNode();
                    }
                    targetNode = GenerateTargetNode();
                    smartNode = GenerateSmartNode();
                }
            }
            while (!isGameOver);
        }

        public void RandomMovement(ConsoleNode gameNode, List<ConsoleNode> list)
        {
            switch (rnd.Next(1, 5))
            {
                case 1:
                    {
                        if (IsOnField(gameNode.X, gameNode.Y - 1) && !IsOnNode(gameNode.X, gameNode.Y - 1))
                        {
                            gameNode.MoveUp();
                        }
                        break;
                    }
                case 2:
                    {
                        if (IsOnField(gameNode.X, gameNode.Y + 1) && !IsOnNode(gameNode.X, gameNode.Y + 1))
                        {
                            gameNode.MoveDown();
                        }
                        break;
                    }
                case 3:
                    {
                        if (IsOnField(gameNode.X - 1, gameNode.Y) && !IsOnNode(gameNode.X - 1, gameNode.Y))
                        {
                            gameNode.MoveLeft();
                        }
                        break;
                    }
                case 4:
                    {
                        if (IsOnField(gameNode.X + 1, gameNode.Y) && !IsOnNode(gameNode.X + 1, gameNode.Y))
                        {
                            gameNode.MoveRight();
                        }
                        break;
                    }
            }
        }

        public Position CheckPosition(int x, int y)
        {
            if (IsOnNode(x, y))
                return Position.Node;
            //if (IsOnField(x, y))
            //    return Position.Free;
            if (IsOnEdge(x, y))
                return Position.Border;
            else return Position.Free;
        }

        private void WriteWinnersList(List<ConsoleNode> list)
        {
            int shiftDown = 5;
            Console.SetCursorPosition(0, field.StartY + field.Height + shiftDown);
            Console.Write("Список победителей:");
            foreach (var node in list)
            {
                Console.SetCursorPosition(0, field.StartY + field.Height + shiftDown + 1);
                Console.Write(node.Symbol);
                shiftDown++;
            }
        }

        private void WriteLooserList(List<ConsoleNode> list)
        {
            int shiftDown = 5;
            Console.SetCursorPosition(30, field.StartY + field.Height + shiftDown);
            Console.Write("Список проигравших:");
            foreach (var node in list)
            {
                Console.SetCursorPosition(30, field.StartY + field.Height + shiftDown + 1);
                Console.Write(node.Symbol);
                shiftDown++;
            }
        }

        public bool IsOnField(int nodeX, int nodeY)
        {
            if (nodeX < field.StartX + field.Width - 1 && nodeX > field.StartX && nodeY > field.StartY && nodeY < field.StartY + field.Height - 1)
            {
                return true;
            }
            return false;
        }

        public bool IsOnNode(int nodeX, int nodeY)
        {
            foreach (var everyGameNode in nodes)
            {
                if (nodeY == everyGameNode.Y && nodeX == everyGameNode.X)
                {
                    return true;
                }
            }
            return false;
        }

        public bool IsOnEdge(int nodeX, int nodeY)
        {
            foreach (var everyGameNode in nodes)
            {
                if (nodeX == field.StartX + field.Width || nodeX == field.StartX-1 || nodeY == field.StartY-1 || nodeY == field.StartY + field.Height)
                {
                    return true;
                }
            }
            return false;
        }
    }
}
    enum Position
    {
        Node,
        Outside,
        Free,
        Border
    }